/** * Copyright 2005-2010 hdiv.org * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hdiv.components; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.faces.FacesException; import javax.faces.component.UIComponent; import javax.faces.component.UIParameter; import javax.faces.component.html.HtmlOutputLink; import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; import javax.servlet.http.HttpServletRequest; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hdiv.config.HDIVConfig; import org.hdiv.dataComposer.IDataComposer; import org.hdiv.util.Constants; import org.hdiv.util.HDIVRequestUtils; import org.hdiv.util.HDIVUtil; import org.hdiv.util.RequestUtilsHDIV; /** * HtmlOutputLink component extension * * @author Gotzon Illarramendi * */ public class HtmlOutputLinkExtension extends HtmlOutputLink { private static Log log = LogFactory.getLog(HtmlOutputLinkExtension.class); /* * (non-Javadoc) * * @see javax.faces.component.UIComponent#encodeBegin(javax.faces.context. * FacesContext) */ public void encodeBegin(FacesContext context) throws IOException { if (log.isDebugEnabled()) { log.debug("encodeBegin"); } try { ExternalContext externalContext = context.getExternalContext(); HttpServletRequest request = (HttpServletRequest) externalContext.getRequest(); String url = this.getValue().toString(); // Check if it is necessary to add the state if (!RequestUtilsHDIV.isInternalUrl(request, url)) { if (log.isDebugEnabled()) { log.debug("is external url"); } super.encodeBegin(context); return; } HDIVConfig hdivConfig = HDIVUtil.getHDIVConfig(request.getSession().getServletContext()); // if url hasn't got parameters, we do not have to include HDIV's // state if (!hdivConfig.isValidationInUrlsWithoutParamsActivated() && !url.contains("?") && !hasUIParamChilds()) { super.encodeBegin(context); return; } // Check if url points to a resource that does not need to be securized, as // an image if (RequestUtilsHDIV.isResourceUrl(hdivConfig, url)) { if (log.isDebugEnabled()) { log.debug("is resource url"); } super.encodeBegin(context); return; } String anchor = HDIVRequestUtils.getAnchorFromUrl(url); url = HDIVRequestUtils.removeAnchorFromUrl(url); IDataComposer dataComposer = HDIVUtil.getDataComposer(request); // Confidentiality is disabled, so the url doesn't change String encodedUrl = RequestUtilsHDIV.composeURL(request, dataComposer, url); boolean hasUIParams = false; Iterator it = this.getChildren().iterator(); while (it.hasNext()) { UIComponent comp = (UIComponent) it.next(); if (comp instanceof UIParameter) { hasUIParams = true; break; } } String requestId = dataComposer.endRequest(); String hdivParameter = (String) externalContext.getSessionMap().get(Constants.HDIV_PARAMETER); if (hasUIParams) { this.setValue(encodedUrl); // Add a children UIParam component with Hdiv's state UIParameter paramComponent = (UIParameter) context.getApplication().createComponent( UIParameter.COMPONENT_TYPE); paramComponent.setName(hdivParameter); paramComponent.setValue(requestId); this.getChildren().add(paramComponent); } else { // Add state directly in the outputLink's value String finalUrl = RequestUtilsHDIV.addHDIVState(hdivParameter, requestId, encodedUrl, anchor); this.setValue(finalUrl); } } catch (FacesException e) { log.error("Error en HtmlOutputLinkExtension: " + e.getMessage()); throw e; } super.encodeBegin(context); } public void encodeEnd(FacesContext context) throws IOException { super.encodeEnd(context); // Remove Hdiv's state component, we don't want to store it in the state String hdivParameter = (String) context.getExternalContext().getSessionMap().get(Constants.HDIV_PARAMETER); Iterator it = this.getChildren().iterator(); // First we add to a list the components to remove // The list used by MyFaces has a problem with the iterator List toRemoveList = new ArrayList(); while (it.hasNext()) { UIComponent comp = (UIComponent) it.next(); if (comp instanceof UIParameter) { UIParameter param = (UIParameter) comp; String name = param.getName(); if (name != null && name.equals(hdivParameter)) { toRemoveList.add(new Integer(this.getChildren().indexOf(param))); } } } // Remove the ones founded before Iterator iter = toRemoveList.iterator(); while (iter.hasNext()) { Integer removeIndex = (Integer) iter.next(); this.getChildren().remove(removeIndex.intValue()); } // Deprecated method in 1.2, but necessary to work in 1.1 if (this.getValueBinding("value") != null) { this.setValue(null); } } /** * Search children component for UIParam components. * * @return */ private boolean hasUIParamChilds() { boolean hasParams = false; Iterator it = this.getChildren().iterator(); while (it.hasNext()) { UIComponent comp = (UIComponent) it.next(); if (comp instanceof UIParameter) { hasParams = true; break; } } return hasParams; } }